<template>
    <div class="login-bg">
        <div class="login-box">
            <div class="login-top">
                <el-image :src="logo" fit="cover" alt="logo"></el-image>
            </div>
            <div class="login-center">
                <el-form
                    :model="data.ruleForm"
                    :rules="data.rules"
                    ref="ruleFormRef"
                >
                    <el-form-item prop="account" required>
                        <el-input
                            v-model.trim="data.ruleForm.account"
                            size="large"
                            prefix-icon="Iphone"
                            placeholder="请输入账号"
                            clearable
                        ></el-input>
                    </el-form-item>
                    <el-form-item prop="pass">
                        <el-input
                            v-model.trim="data.ruleForm.pass"
                            prefix-icon="Lock"
                            placeholder="请输入密码"
                            clearable
                            size="large"
                            show-password
                        >
                        </el-input>
                    </el-form-item>
                    <el-form-item prop="code" required>
                        <el-input
                            style="flex: 1"
                            v-model.trim="data.ruleForm.code"
                            @keyup.enter.native="submitForm(ruleFormRef)"
                            size="large"
                            prefix-icon="Warning"
                            placeholder="请输入验证码"
                            clearable
                        ></el-input>
                        <img
                            :src="codeUrl.img"
                            @click="getCode"
                            class="login-code-img"
                        />
                    </el-form-item>

                    <el-form-item class="form-btn">
                        <el-button
                            color="#0099cc"
                            size="large"
                            :loading="btn_loading"
                            @click="submitForm(ruleFormRef)"
                        >
                            登录</el-button
                        >
                    </el-form-item>
                </el-form>
            </div>
            <p class="copyright">
                <el-link
                    href="http://www.huashuyn.com/"
                    :underline="false"
                    target="_blank"
                    >©技术支持：花数通</el-link
                >
            </p>
        </div>

        <vue-particles id="tsparticles" :options="options" />

        <!-- 滑块+拼图验证 -->
        <el-dialog
            v-model="dialogSlider"
            title="拼图验证"
            width="300px"
            top="29vh"
            :append-to-body="true"
            :destroy-on-close="true"
            :close-on-click-modal="false"
            @close="dialogSlider = false"
        >
            <slide-verify
                ref="sliderImg"
                :slider-text="sliderText"
                :accuracy="4"
                :show="false"
                :imgs="imgArr"
                :w="260"
                :h="220"
                @again="onAgain"
                @success="onSuccess"
                @fail="onFail"
            ></slide-verify>
        </el-dialog>
    </div>
</template>

<script setup>
import { ref, reactive, onMounted, onBeforeUnmount, inject } from "vue";
import { useRouter } from "vue-router";
import { useUserStore } from "@stores/user";
import logo from "@assets/logo.png";
import img1 from "@images/img1.jpg";
import img2 from "@images/img2.jpg";
import img3 from "@images/img3.jpg";
import SlideVerify from "vue3-slide-verify";
import "vue3-slide-verify/dist/style.css";
import JSEncrypt from "jsencrypt";
import { getEncrypt, getCaptcha, loginByPc } from "@/apis/login";

const $message = inject("$message");
const router = useRouter();
const userStore = useUserStore();

onMounted(() => {
    getKey();
    getCode();
});
onBeforeUnmount(() => {
    sliderImg.value = null;
    ruleFormRef.value = null;
    imgArr.value = [];
    options = null;
    dialogSlider.value = false;
});
let options = {
    fpsLimit: 100,
    interactivity: {
        events: {
            onClick: {
                enable: true,
                mode: "push",
            },
            onHover: {
                enable: true,
                mode: "grab",
            },
            resize: true,
        },
        modes: {
            bubble: {
                distance: 400,
                duration: 2,
                opacity: 0.6,
                size: 10,
            },
            push: {
                quantity: 4,
            },
            repulse: {
                distance: 200,
                duration: 0.4,
            },
        },
    },
    particles: {
        color: {
            value: "#ffffff",
        },
        links: {
            color: "#ffffff",
            distance: 150,
            enable: true,
            opacity: 0.5,
            width: 1,
        },
        collisions: {
            enable: true,
        },
        move: {
            direction: "none",
            enable: true,
            outMode: "bounce",
            random: false,
            speed: 2,
            straight: false,
        },
        number: {
            density: {
                enable: true,
                value_area: 800,
            },
            value: 60,
        },
        opacity: {
            value: 0.5,
        },
        shape: {
            type: "circle",
        },
        size: {
            random: true,
            value: 3,
        },
    },
    detectRetina: true,
};
const data = reactive({
    ruleForm: {
        account: "",
        pass: "",
        code: "",
    },
    rules: {
        account: [{ required: true, message: "请输入账号", trigger: "blur" }],
        pass: [{ required: true, message: "请输入密码", trigger: "blur" }],
        code: [{ required: true, message: "请输入验证码", trigger: "blur" }],
    },
});

const ruleFormRef = ref(null);
const btn_loading = ref(false);

/**
 * 滑块+拼图验证 vue3-slide-verify
 * @param {Number} w canvas width
 * @param {Number} h canvas height
 * @param {Number} accuracy 滑动验证的误差范围，默认值 5
 * @param {Array} imgs picture array 背景图数组，默认值 []
 * @param {String} sliderText 滑块中提示文字
 * @param {Function} onAgain 检测到非人为操作滑动时触发的回调函数
 * @param {Function} onSuccess 成功回调
 * @param {Function} onFail 失败处理
 * @param {Function} onRefresh 点击刷新按钮后
 */
const sliderText = ref("向右滑动 >>");
const imgArr = ref([img1, img2, img3]);
const sliderImg = ref(null);
const dialogSlider = ref(false);
const onAgain = () => {
    $message({ message: "检测到非人为操作！ try again", type: "error" });
    sliderImg.value.refresh(); // 刷新
};
const onSuccess = (times) => {
    logins();
};
const onFail = () => {
    $message({ message: "验证不通过", type: "error" });
};

const submitForm = (formEl) => {
    if (!formEl) return;
    formEl.validate((valid, fields) => {
        if (valid) {
            // dialogSlider.value = true
            logins();
        }
    });
};

async function logins() {
    // sliderImg.value.refresh() // 刷新
    // dialogSlider.value = false
    btn_loading.value = true;
    let encryptor = new JSEncrypt(); // 创建加密对象实例
    encryptor.setPublicKey(pub_keys.value); // 设置公钥
    let pass = encryptor.encrypt(data.ruleForm.pass); // 对内容进行加密
    try {
        const res = await loginByPc(
            {
                userName: data.ruleForm.account,
                password: pass,
            },
            {
                headers: {
                    CAP_UID: codeUrl.value.uuid,
                    CAP_VAL: data.ruleForm.code,
                },
            }
        );

        btn_loading.value = false;
        switch (res.data.code) {
            case 200:
                let result = res.data.data;
                localStorage.setItem("token", "Bearer " + result.accessToken);
                if (result.admin) {
                    userStore.setPermissions(["*:*:*"]);
                } else {
                    userStore.setPermissions(result.permissionSet);
                }
                userStore.setRoleKeySet(result.roleKeySet);
                userStore.setMenuTree(result.menuTree);
                userStore.clearCurFirstNavIndex();
                userStore.setCurFirstNavIndex(0);
                userStore.initKeepAlive();
                userStore.setInfo({
                    nickName: result.nickName,
                });
                router.replace("/Home");
                break;
            default:
                getCode();
                $message({ message: res.data.msg, type: "error" });
                break;
        }
    } catch {
        btn_loading.value = false;
    }
}

const pub_keys = ref("");
async function getKey() {
    const res = await getEncrypt();
    if (res.data.code == 200) {
        pub_keys.value = res.data.data;
    } else {
        $message({ message: res.data.msg, type: "error" });
    }
}

const codeUrl = ref("");
async function getCode() {
    const res = await getCaptcha();
    if (res.data.code == 200) {
        codeUrl.value = res.data.data;
    } else {
        $message({ message: res.data.msg, type: "error" });
    }
}
</script>

<style lang="less" scoped>
:deep(.el-dialog__body) {
    padding: 10px 20px 20px;
}

.copyright {
    width: 100%;
    text-align: center;

    .el-link.el-link--default {
        color: #999;

        &:hover {
            color: #0099cc;
        }
    }
}

.login-box {
    z-index: 10;
    width: 400px;
    border-radius: 5px;
    padding-bottom: 50px;
    background: white;
    box-shadow: 0px 0px 5px #333333;

    .login-top {
        width: 100%;
        text-align: center;
        margin-top: 35px;
        margin-bottom: 20px;

        .el-image {
            width: 220px;
        }
    }

    .login-center {
        padding: 0 60px;
    }

    :deep(.el-form-item__label) {
        &::before {
            content: "" !important;
        }
    }

    .form-btn {
        margin: 44px 0px 20px;

        :deep(.el-form-item__content) {
            margin: 0 !important;

            .el-button {
                width: 100%;
                letter-spacing: 1px;
            }
        }
    }
}

.login-code-img {
    width: 100px;
    height: 36px;
    margin-left: 10px;
}

.login-bg {
    width: 100%;
    height: 100%;
    background: url("../assets/images/bg.jpg") no-repeat center;
    background-size: cover;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    overflow: hidden;
    position: relative;
}
</style>
